﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;

namespace WebParser
{
    public abstract class BaseService
    {
        public event CancelEventHandler Starting;
        public event CancelEventHandler Stopping;
        public event EventHandler       Started ;
        public event EventHandler       Stopped ;

        protected virtual void OnStarting   (CancelEventArgs e  ) { if (Starting  != null) Starting  (this, e); }
        protected virtual void OnStopping   (CancelEventArgs e  ) { if (Stopping  != null) Stopping  (this, e); }
        protected virtual void OnStarted    (EventArgs e        ) { if (Started   != null) Started   (this, e); }
        protected virtual void OnStopped    (EventArgs e        ) { if (Stopped   != null) Stopped   (this, e); }

        private readonly List<object> _sync;
        protected bool GetSync(object token)
        {
            return _sync.Contains(token);
        }
        protected void SetSync(object token, bool enable)
        {
            var contains = _sync.Contains(token);
            if ((enable && contains) || (!enable && !contains)) return;
            if (enable)
                _sync.Add(token);
            else
                _sync.Remove(token);
        }
        public bool IsRunning
        {
            get { return GetSync("IsRunning"); }
            private set { SetSync("IsRunning", value); }
        }
        protected bool KeepRunning
        {
            get { return GetSync("KeepRunning"); }
            set { SetSync("KeepRunning", value); }
        }

        protected BaseService()
        {
            _sync = new List<object>();
        }
        public bool Start()
        {
            if (IsRunning) return false;
            IsRunning = true;
            var e = new CancelEventArgs(false);
            OnStarting(e);
            if (e.Cancel) return false;
            if (!PrepareStart()) return false;
            new Thread(LaunchCoreJob) {IsBackground = true}.Start();
            OnStarted(EventArgs.Empty);
            return true;
        }
        protected abstract bool PrepareStart();
        protected abstract void ContinuableRunningJob();
        private void LaunchCoreJob()
        {
            KeepRunning = true;
            ContinuableRunningJob();
            IsRunning = false;
        }
        public void Stop()
        {
            if (!IsRunning) return;
            var e = new CancelEventArgs(false);
            OnStopping(e);
            if (e.Cancel) return;
            KeepRunning = false;
        }
    }
}